package com.bree.erp.service.stateless;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.apache.log4j.Logger;

import com.bree.erp.entity.ItemRequest;
import com.bree.erp.entity.PartUnit;
import com.bree.erp.entity.PoItem;
import com.bree.erp.entity.PurchaseOrder;
import com.bree.erp.entity.PurchaseRequisition;
import com.bree.erp.service.PoItemService;

@Stateless
public class PoItemServiceBean implements PoItemService {

	private static Logger LOG = Logger.getLogger(PoItemServiceBean.class);
			
	@PersistenceContext()
	private EntityManager em;
	
	public PoItemServiceBean() {
		
	}
	
	public PoItemServiceBean(EntityManager em) {
		this.em = em;
	}
	
	@Override
	public PoItem create(Long poId, Long partUnitId, double pricePerUnit, double quantity) {
		PoItem poItem = new PoItem();
	
		PurchaseOrder po = em.find(PurchaseOrder.class, poId);
		
		LOG.debug(poId + " is " + po);
		
		PartUnit partUnit = em.find(PartUnit.class, partUnitId);
		
		poItem.setPurchaseOrder(po);
		poItem.setPartUnit(partUnit);
		poItem.setPricePerUnit(pricePerUnit);
		poItem.setQuantity(quantity);
		
		// calculate total price.
		double totalPrice = poItem.getPricePerUnit() * quantity;
		poItem.setTotalPrice(totalPrice);
		
		em.persist(poItem);
		LOG.debug("before: " + po.getItems().size());
		po.getItems().add(poItem);
		LOG.debug("after: " + po.getItems().size());
		
		return poItem;
	}

	@Override
	public PoItem read(Long id) {
		
		return em.find(PoItem.class, id);
	}

	@Override
	public PoItem update(Long id, double totalPrice, String remarks) {
		
		PoItem poItem = read(id);
		
		poItem.setTotalPrice(totalPrice);
		poItem.setRemarks(remarks);
		
		return poItem;
	}

	@Override
	public PoItem update(Long id, double quantity) {

		PoItem poItem = read(id);
		
		poItem.setQuantity(quantity);
		
		// re-compute total price
		double totalPrice = quantity * poItem.getPricePerUnit();
		poItem.setTotalPrice(totalPrice);
		
		return poItem;
	}

	@Override
	public void delete(Long id) {
		PoItem poItem = read(id);
		
		em.remove(poItem);
	}

	@Override
	public double totalQuantity(Long prId, Long partUnitId) {
		
		LOG.debug("totalQuantity(prId: " + prId + "; partUnitId: " + partUnitId);

		PurchaseRequisition pr = em.find(PurchaseRequisition.class, prId);
		
		em.refresh(pr);
		
		double total = 0;
		for(PurchaseOrder order : pr.getOrders()) {
			for(PoItem item : order.getItems()) {
				if(partUnitId.equals(item.getPartUnit().getId())) {
					total += item.getQuantity();
				}
			}
		}

		return total;
	}
	
	@Override
	public Map<PartUnit, Double> totalQuantity(Long prId) {
		
		Map<PartUnit, Double> map = new HashMap<PartUnit, Double>();

		PurchaseRequisition pr = em.find(PurchaseRequisition.class, prId);
		
		em.refresh(pr);
		
		// init map content
		for(ItemRequest req : pr.getRequests()) {
			map.put(req.getPartUnit(), 0.0);
		}
		
		// compute total
		for(PurchaseOrder order : pr.getOrders()) {
			for(PoItem item : order.getItems()) {
				PartUnit key = item.getPartUnit();
				double total = map.get(key) + item.getQuantity();
				map.put(key, total);
			}
		}

		return map;
	}

	@Override
	public Collection<PoItem> list(Long poId) {
		
		PurchaseOrder po = em.find(PurchaseOrder.class, poId);
		return po.getItems();
	}

}
